package perform.utilities;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import perform.exception.ResultProcessingException;
import perform.mappings.ClassMappings;
import perform.type.Type;
import perform.type.Wrapper;

public class ResultProcessor {
	
	private ValueParser parser;
	private Wrapper wrapper;
	
	public ResultProcessor(){
		parser = new ValueParser();
		wrapper = new Wrapper();
	}
	public <T extends Type> T process(T type, ResultSet rs) throws ResultProcessingException{
		try {
			if(rs.next()){
				Map<Field, String> map = ClassMappings.getAllColumns(type.getClass());
				Field[] fields = map.keySet().toArray(new Field[map.size()]);
				for (int i = 0; i < fields.length; i++) {
					fields[i].set(type, parser.parseValue(fields[i].getType(), map.get(fields[i]), rs));
				}
				wrapper.setSaved(type, true);
				return type;
			}
			return null;
		} catch (Exception e) {
			throw new ResultProcessingException(e);
		}
	}
	public <T extends Type> List<T> process(Class<T> clazz, ResultSet rs) throws ResultProcessingException{
		try {
			List<T> results = new ArrayList<T>();
			Map<Field, String> map = ClassMappings.getAllColumns(clazz);
			Field[] fields = map.keySet().toArray(new Field[map.size()]);
			while(rs.next()){
				T result = clazz.newInstance();
				for (int i = 0; i < fields.length; i++) {
					fields[i].set(result, parser.parseValue(fields[i].getType(), map.get(fields[i]), rs));
				}
				wrapper.setSaved(result, true);
				results.add(result);
			}
			if(!results.isEmpty()){
				return results;
			}
			return null;
		} catch (Exception e) {
			throw new ResultProcessingException(e);
		}
	}
	@SuppressWarnings("unchecked")
	public <T extends Type> T[] processArray(Class<T> clazz, ResultSet rs) throws ResultProcessingException{
		try {
			List<T> list = process(clazz, rs);
			if(list != null){
				T[] array = (T[]) Array.newInstance(clazz, list.size());
				return list.toArray(array);
			}
			return null;
		} catch (ResultProcessingException e) {
			throw e;
		} catch (Exception e){
			throw new ResultProcessingException(e);
		}
	}

}
